package com.uinnova.product.eam.service.flowable.impl;

import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.uinnova.product.eam.base.exception.ServerException;
import com.uinnova.product.eam.comm.model.es.EamCategory;
import com.uinnova.product.eam.feign.workable.FlowableFeign;
import com.uinnova.product.eam.feign.workable.entity.PorcessResponse;
import com.uinnova.product.eam.model.cj.domain.PlanDesignInstance;
import com.uinnova.product.eam.model.constants.FlowableConstant;
import com.uinnova.product.eam.service.*;
import com.uinnova.product.eam.service.asset.BmConfigSvc;
import com.uinnova.product.eam.service.cj.service.PlanDesignInstanceService;
import com.uinnova.product.eam.service.flowable.FlowableApprovalUserSvc;
import com.uinnova.product.eam.service.fx.GeneralPushSvc;
import com.uinnova.project.base.diagram.comm.model.ESDiagram;
import com.uinnova.project.service.eam.ESDiagramSvc;
import com.uino.api.client.cmdb.ICIClassApiSvc;
import com.uino.api.client.permission.IRoleApiSvc;
import com.uino.api.client.permission.IUserApiSvc;
import com.uino.bean.cmdb.base.LibType;
import com.uino.bean.permission.base.SysOrg;
import com.uino.bean.permission.base.SysRole;
import com.uino.bean.permission.base.SysUser;
import com.uino.bean.permission.business.UserInfo;
import com.uino.bean.permission.query.UserSearchBeanExtend;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class EamApprovalUserSvc implements FlowableApprovalUserSvc {

    @Resource
    private IUserApiSvc userApiSvc;
    @Resource
    private IRoleApiSvc roleApiSvc;
    @Resource
    private FlowableFeign flowableFeign;
    @Resource
    private GeneralPushSvc generalPushSvc;
    @Resource
    private EamCategorySvc categorySvc;
    @Resource
    private ESDiagramSvc esDiagramSvc;
    @Resource
    private IFolderApprovalManagerSvc approvalManagerSvc;
    @Resource
    private PlanDesignInstanceService planInstanceService;

    @Override
    public List<String> getApprovalUser(String defKey, String businessKey, String taskKey) {
        //新网模型资产审批人
//        if (FlowableConstant.MODEL_DEFINITION_KEY.equals(defKey)) {
//            return getModelApproveUsers(businessKey, taskKey);
//        }
        //第一个节点,组织架构评审
        List<String> result = new ArrayList<>();
        String userCode = getUserCode(defKey, businessKey);
        //业务方案审批人
//        if (FlowableConstant.XW_BUSINESS_SCENARIO_APPROVE.equals(defKey)) {
//            return getBusinessScenarioApproveUsers(businessKey, taskKey, userCode);
//        }
        EamCategory category = checkAssetDir(defKey, businessKey);
        if(category == null){
            log.error("未查询到审批用户,资产文件夹已删除!");
            return result;
        }
        if(FlowableConstant.ORGANIZE_TASK_KEY.equals(taskKey)){
            log.info("查询审批用户：userCode={}", userCode);
            //查询发布人所在组织,找到组织下一级审批角色的用户,如果找不到找admin角色用户
            UserInfo pushUser = userApiSvc.getUserInfoByLoginCode(userCode);
            Set<Long> pushOrgIds = pushUser.getOrgs().stream().map(SysOrg::getId).collect(Collectors.toSet());
            result = getApprovalUserByOrg(FlowableConstant.APPROVAL_ROLE, pushOrgIds);
            if(CollectionUtils.isEmpty(result)){
                result = getApprovalUserByOrg(FlowableConstant.ADMIN_ROLE, null);
            }
            if(CollectionUtils.isEmpty(result)){
                log.error("未获取到审批用户");
            }
        } else if (FlowableConstant.CATEGORY_TASK_KEY.equals(taskKey)) {
            log.info("查询审批用户：dirId={}", category.getId());
            result = queryDirApprovalUser(category);
            if(CollectionUtils.isEmpty(result)){
                log.info("开始查询admin审批用户,taskKey:{}", taskKey);
                UserInfo pushUser = userApiSvc.getUserInfoByLoginCode(userCode);
                Set<Long> pushOrgIds = pushUser.getOrgs().stream().map(SysOrg::getId).collect(Collectors.toSet());
                result = getApprovalUserByOrg(FlowableConstant.ADMIN_ROLE, null);
            }
            if(CollectionUtils.isEmpty(result)){
                log.error("资产文件夹{}未配置审批用户,文件夹Id:{}", category.getDirName(), category.getId());
            }
        }else{
            log.error("未获取到审批用户,任务节点标识有误!");
        }
        return result;
    }

    /**
     * 递归查询文件夹及父级文件夹配置的审批用户(如果当前文件夹没配置，就从下往上找)
     * @param category 当前文件夹
     * @return 审批用户code集合
     */
    private List<String> queryDirApprovalUser(EamCategory category){
        List<String> result = approvalManagerSvc.queryDirApprovalUser(category.getId());
        if(CollectionUtils.isEmpty(result)){
            if(BinaryUtils.isEmpty(category.getParentId()) || category.getParentId().equals(0L)){
                return result;
            }
            EamCategory parent = categorySvc.getById(category.getParentId(), LibType.DESIGN);
            if(parent != null){
                return queryDirApprovalUser(parent);
            }
        }
        return result;
    }

    /**
     * 查询流程发起人
     * @param defKey 流程定义key
     * @param businessKey 业务定义key(方案id OR 视图id)
     * @return 用户标识
     */
    private String getUserCode(String defKey, String businessKey) {
        String userCode = null;
        if(FlowableConstant.DIAGRAM_DEFINITION_KEY.equals(defKey)){
            ESDiagram diagram = esDiagramSvc.getEsDiagram(businessKey, 0);
            if(diagram == null){
                log.error("未获取到审批用户,视图已删除,diagramId={}", businessKey);
                throw new ServerException("未获取到审批用户!");
            }
            userCode = diagram.getOwnerCode();
        }else if(FlowableConstant.PLAN_DEFINITION_KEY2.equals(defKey)
                || FlowableConstant.XW_BUSINESS_SCENARIO_APPROVE.equals(defKey)){
            PlanDesignInstance planInstance = planInstanceService.getPlanDesignInstance(Long.valueOf(businessKey));
            userCode = planInstance.getCreatorCode();
        }
        return userCode;
    }

    /**
     * 校验资产文件夹是否删除
     * @param defKey 流程定义key
     * @param businessKey 业务定义key(方案id OR 视图id)
     * @return 资产文件夹id
     */
    private EamCategory checkAssetDir(String defKey, String businessKey){
        PorcessResponse processInstance = flowableFeign.getProcessInstanceByBusinessIdAndProcessDefinitionKey(businessKey, defKey);
        Map<String, Object> variables = processInstance.getRouterVariables();
        Object dirIdObj = variables.get("releaseDirId");
        Assert.notNull(dirIdObj, "文件夹id为空");
        //发布至资产文件夹id
        Long dirId = Long.parseLong(dirIdObj.toString());
        //校验资产文件夹是否还在
        return categorySvc.getById(dirId, LibType.DESIGN);
    }

    private List<String> getApprovalUserByOrg(String orgName, Set<Long> pushOrgIds){
        List<SysRole> roles = roleApiSvc.getRolesByQuery(QueryBuilders.termQuery("roleName.keyword", orgName));
        if(CollectionUtils.isEmpty(roles)){
            return Collections.emptyList();
        }
        Long roleId = roles.get(0).getId();
        UserSearchBeanExtend beanExtend = new UserSearchBeanExtend();
        beanExtend.setPageNum(1);
        //审批人暂定200
        beanExtend.setPageSize(200);
        beanExtend.setRoleId(roleId);
        if(CollectionUtils.isNotEmpty(pushOrgIds)){
            beanExtend.setOrgIds(pushOrgIds);
        }
        beanExtend.setOnlyCurrentOrg(true);
        Page<UserInfo> userInfoPage = userApiSvc.getListByQuery(beanExtend);
        if(CollectionUtils.isEmpty(userInfoPage.getData())){
            return Collections.emptyList();
        }
        return userInfoPage.getData().stream().map(SysUser::getLoginCode).distinct().collect(Collectors.toList());
    }
}
